using Sage.CloudStorage.Qiniu.Models;
using Sage.Http.Authentication;
using System.Net.Http.Headers;

namespace Sage.CloudStorage.Qiniu.Auth
{
    /// <summary>
    /// 七牛云认证提供者 - 支持多种认证类型的统一认证接口
    /// </summary>
    /// <remarks>
    /// 这是七牛云SDK的核心认证组件，实现了IAuthenticationProvider接口，
    /// 为不同的七牛云API场景提供相应的认证方式。
    /// 
    /// **核心特性**：
    /// - **多认证支持**：支持5种不同的认证类型，覆盖所有七牛云API场景
    /// - **完全异步**：避免同步等待异步操作可能导致的死锁和性能问题
    /// - **自动适配**：根据认证类型自动选择正确的签名算法和请求格式
    /// - **安全可靠**：严格按照七牛云官方认证规范实现
    /// 
    /// **支持的认证类型**：
    /// - **ManageApi**：传统QBox格式的管理API认证
    /// - **ManageApiV2**：新版Qiniu格式的管理API认证（推荐）
    /// - **Upload**：文件上传认证，生成上传凭证
    /// - **Download**：私有文件下载认证，为URL添加签名参数
    /// - **StreamManage**：流媒体管理认证
    /// 
    /// **性能优化**：
    /// - 异步IO操作：所有网络和文件操作都是异步的
    /// - 内存优化：使用流处理大型请求体，避免内存占用过高
    /// - 连接复用：配合HTTP客户端实现连接池和复用
    /// 
    /// **使用建议**：
    /// - 对于新项目，推荐使用ManageApiV2类型
    /// - 上传大文件时使用Upload类型配合分片上传
    /// - 私有资源访问使用Download类型
    /// - 直播相关功能使用StreamManage类型
    /// </remarks>
    public class QiniuAuthProvider : IAuthenticationProvider
    {
        /// <summary>
        /// 七牛云签名计算器，负责各种签名算法的实现
        /// </summary>
        private readonly QiniuSignature _signature;

        /// <summary>
        /// 当前认证提供者的认证类型，决定使用哪种认证方式
        /// </summary>
        private readonly QiniuAuthType _authType;

        /// <summary>
        /// 上传策略JSON字符串，仅在Upload认证类型时使用
        /// 包含上传权限、过期时间、回调设置等策略信息
        /// </summary>
        private readonly string? _uploadPolicy;

        /// <summary>
        /// 下载链接有效期，仅在Download认证类型时使用
        /// 用于生成带过期时间的私有文件下载链接
        /// </summary>
        private readonly TimeSpan? _expiry;

        /// <summary>
        /// 管理API认证构造函数
        /// 用于创建存储桶管理、文件管理等管理类API的认证提供者
        /// </summary>
        /// <param name="qiniuKey">七牛云密钥信息（AccessKey和SecretKey）</param>
        /// <param name="authType">认证类型，默认使用V2版本（推荐）</param>
        /// <exception cref="ArgumentNullException">当qiniuKey为null时抛出</exception>
        /// <remarks>
        /// 适用场景：
        /// - **存储桶操作**：创建、删除、列举存储桶
        /// - **文件管理操作**：删除、移动、复制、重命名文件
        /// - **统计查询**：获取存储使用情况、流量统计等
        /// - **域名管理**：绑定、解绑自定义域名
        /// - **CDN配置**：缓存策略、防盗链设置等
        /// 
        /// 推荐使用ManageApiV2类型，具有更好的安全性和兼容性：
        /// - 安全性更高：包含更多请求信息，防篡改能力强
        /// - 兼容性好：支持所有新版七牛云API
        /// - 扩展性强：支持自定义头部验证
        /// - 标准化：符合现代API安全标准
        /// 
        /// 使用示例：
        /// ```csharp
        /// var qiniuKey = new QiniuKey("AccessKey", "SecretKey");
        /// var authProvider = new QiniuAuthProvider(qiniuKey, QiniuAuthType.ManageApiV2);
        /// // 将authProvider传递给HTTP客户端使用
        /// ```
        /// </remarks>
        public QiniuAuthProvider(QiniuKey qiniuKey, QiniuAuthType authType = QiniuAuthType.ManageApiV2)
        {
            ArgumentNullException.ThrowIfNull(qiniuKey, nameof(qiniuKey));

            _signature = new QiniuSignature(qiniuKey);
            _authType = authType;
        }

        /// <summary>
        /// 上传凭证构造函数
        /// 用于创建文件上传场景的认证提供者
        /// </summary>
        /// <param name="qiniuKey">七牛云密钥信息</param>
        /// <param name="uploadPolicy">上传策略的JSON字符串</param>
        /// <exception cref="ArgumentNullException">当qiniuKey或uploadPolicy为null时抛出</exception>
        /// <exception cref="ArgumentException">当uploadPolicy为空字符串时抛出</exception>
        /// <remarks>
        /// 上传策略是控制文件上传行为的核心配置，通常包含以下信息：
        /// 
        /// **必需参数**：
        /// - **scope**：上传的目标存储桶和文件名
        /// - **deadline**：上传凭证的过期时间戳
        /// 
        /// **可选参数**：
        /// - **callbackUrl**：上传成功后的回调地址
        /// - **callbackBody**：回调请求的内容
        /// - **returnBody**：直接返回给客户端的内容
        /// - **insertOnly**：是否仅允许新增文件（不能覆盖）
        /// - **fsizeLimit**：文件大小限制
        /// - **mimeLimit**：文件类型限制
        /// - **persistentOps**：持久化处理操作（如转码、截图等）
        /// 
        /// **使用场景**：
        /// - **客户端直传**：生成上传凭证供前端直接上传到七牛云
        /// - **服务端代理上传**：服务端使用凭证代理上传文件
        /// - **分片上传**：大文件的分片上传场景
        /// - **移动端上传**：移动应用的文件上传功能
        /// 
        /// **安全注意事项**：
        /// - 上传凭证包含明文的上传策略，客户端可以解码查看
        /// - 建议根据实际需求设置合理的有效期（通常1-24小时）
        /// - 对于敏感的上传场景，可以在策略中添加额外的安全限制
        /// - 不要在客户端硬编码SecretKey，应该由服务端生成凭证
        /// 
        /// 使用示例：
        /// ```csharp
        /// var policy = new UploadPolicy 
        /// {
        ///     Scope = "my-bucket:path/file.jpg",
        ///     Deadline = DateTimeOffset.UtcNow.AddHours(1).ToUnixTimeSeconds(),
        ///     FsizeLimit = 10 * 1024 * 1024, // 10MB限制
        ///     MimeLimit = "image/*"
        /// };
        /// var authProvider = new QiniuAuthProvider(qiniuKey, policy.ToJson());
        /// ```
        /// </remarks>
        public QiniuAuthProvider(QiniuKey qiniuKey, string uploadPolicy)
        {
            ArgumentNullException.ThrowIfNull(qiniuKey, nameof(qiniuKey));
            ArgumentNullException.ThrowIfNull(uploadPolicy, nameof(uploadPolicy));

            if (string.IsNullOrWhiteSpace(uploadPolicy))
                throw new ArgumentException("上传策略不能为空白字符串", nameof(uploadPolicy));

            _signature = new QiniuSignature(qiniuKey);
            _authType = QiniuAuthType.Upload;
            _uploadPolicy = uploadPolicy;
        }

        /// <summary>
        /// 下载凭证构造函数
        /// 用于创建私有文件下载场景的认证提供者
        /// </summary>
        /// <param name="qiniuKey">七牛云密钥信息</param>
        /// <param name="expiry">下载链接的有效期</param>
        /// <exception cref="ArgumentNullException">当qiniuKey为null时抛出</exception>
        /// <remarks>
        /// 下载认证用于为私有存储桶中的文件生成临时访问链接，提供细粒度的访问控制。
        /// 
        /// **适用场景**：
        /// - **私有存储桶**：需要访问控制的文件下载
        /// - **付费内容**：需要权限验证的资源访问
        /// - **防盗链保护**：防止直链被恶意使用和盗用
        /// - **临时分享**：生成有时效性的分享链接
        /// - **会员内容**：仅限会员访问的资源
        /// - **敏感资料**：需要审计和控制的文档访问
        /// 
        /// **工作原理**：
        /// 1. **添加过期时间**：为原始URL添加过期时间参数（e=时间戳）
        /// 2. **计算签名**：对包含过期时间的URL进行HMAC-SHA1签名
        /// 3. **生成最终URL**：将签名作为token参数添加到最终URL中
        /// 4. **服务器验证**：七牛云服务器验证签名和过期时间的有效性
        /// 
        /// **安全特性**：
        /// - **时效性**：链接在指定时间后自动失效，防止长期滥用
        /// - **签名验证**：防止URL参数被篡改，确保访问安全
        /// - **访问控制**：只有知道完整签名URL的用户才能访问
        /// - **审计友好**：每次访问都需要重新生成，便于访问记录
        /// 
        /// **有效期建议**：
        /// - **临时预览**：5-30分钟，适合快速查看
        /// - **下载链接**：1-4小时，适合用户下载
        /// - **分享链接**：1-24小时，适合短期分享
        /// - **长期访问**：不建议超过7天，安全风险较高
        /// 
        /// **注意事项**：
        /// - 生成的URL较长，包含签名信息，不适合手动输入
        /// - 仅适用于私有存储桶，公有存储桶通常不需要下载认证
        /// - 下载认证会直接修改请求的URL，不使用Authorization头部
        /// - 签名URL不能缓存太久，建议动态生成
        /// 
        /// 使用示例：
        /// ```csharp
        /// var qiniuKey = new QiniuKey("AccessKey", "SecretKey");
        /// var authProvider = new QiniuAuthProvider(qiniuKey, TimeSpan.FromMinutes(30));
        /// // 生成的URL格式：https://domain.com/file.jpg?e=1640995200&amp;token=AccessKey:签名
        /// ```
        /// </remarks>
        public QiniuAuthProvider(QiniuKey qiniuKey, TimeSpan expiry)
        {
            ArgumentNullException.ThrowIfNull(qiniuKey, nameof(qiniuKey));

            _signature = new QiniuSignature(qiniuKey);
            _authType = QiniuAuthType.Download;
            _expiry = expiry;
        }

        /// <summary>
        /// 创建下载凭证
        /// </summary>
        /// <param name="url">原始URL</param>
        /// <param name="deadline">过期时间戳（Unix时间戳）</param>
        /// <returns>下载凭证</returns>
        /// <exception cref="ArgumentNullException">当url为null时抛出</exception>
        /// <remarks>
        /// 此方法用于生成私有资源的下载凭证，用于构建带有授权的下载链接
        /// </remarks>
        public string CreateDownloadToken(string url, long deadline)
        {
            ArgumentException.ThrowIfNullOrEmpty(url, nameof(url));

            // 为URL添加过期时间参数
            var urlWithExpiry = url.Contains('?')
                ? $"{url}&e={deadline}"  // URL已有参数，使用&连接
                : $"{url}?e={deadline}"; // URL无参数，使用?开始

            // 对包含过期时间的URL进行签名
            return _signature.Sign(urlWithExpiry);
        }

        /// <summary>
        /// 为HTTP请求应用认证信息（异步版本）
        /// 这是IAuthenticationProvider接口的核心方法，会被HTTP请求管理器自动调用
        /// </summary>
        /// <param name="request">待认证的HTTP请求对象</param>
        /// <returns>异步任务</returns>
        /// <exception cref="ArgumentNullException">当request为null时抛出</exception>
        /// <exception cref="NotSupportedException">当认证类型不支持时抛出</exception>
        /// <exception cref="InvalidOperationException">当认证过程中出现配置错误时抛出</exception>
        /// <remarks>
        /// 这是认证提供者的核心方法，根据初始化时指定的认证类型，自动选择相应的认证方式：
        /// 
        /// **认证流程**：
        /// 1. **参数验证**：检查请求对象是否有效
        /// 2. **类型判断**：根据_authType选择认证算法
        /// 3. **签名生成**：调用相应的签名方法
        /// 4. **请求修改**：将认证信息添加到请求中
        /// 5. **异常处理**：包装和处理认证过程中的异常
        /// 
        /// **认证类型处理**：
        /// - **ManageApi**：使用QBox格式的Authorization头
        /// - **ManageApiV2**：使用Qiniu格式的Authorization头
        /// - **Upload**：添加X-Qiniu-Upload-Token自定义头
        /// - **Download**：修改请求URL添加签名参数
        /// - **StreamManage**：使用Qiniu格式的Authorization头，对请求体签名
        /// 
        /// **异步优势**：
        /// - **非阻塞**：避免阻塞调用线程，提高系统响应性
        /// - **防死锁**：避免同步等待异步操作导致的死锁问题
        /// - **高并发**：在高并发场景下提供更好的性能表现
        /// - **可扩展**：为未来的异步认证扩展提供基础
        /// 
        /// **实现细节**：
        /// - 使用ConfigureAwait(false)避免不必要的上下文切换
        /// - 异步读取请求体内容，适合处理大型请求
        /// - 完善的异常处理和包装机制
        /// - 线程安全的实现，支持并发调用
        /// 
        /// 使用示例：
        /// ```csharp
        /// var request = new HttpRequestMessage(HttpMethod.Get, "https://api.qiniu.com/v1/resource");
        /// await authProvider.AuthenticateRequest(request);
        /// // 请求现在包含了正确的认证信息
        /// ```
        /// </remarks>
        public async Task AuthenticateRequest(HttpRequestMessage request)
        {
            ArgumentNullException.ThrowIfNull(request, nameof(request));

            try
            {
                // 根据认证类型选择相应的认证方式
                switch (_authType)
                {
                    case QiniuAuthType.ManageApi:
                        await ApplyManageApiAuthAsync(request).ConfigureAwait(false);
                        break;

                    case QiniuAuthType.ManageApiV2:
                        await ApplyManageApiV2AuthAsync(request).ConfigureAwait(false);
                        break;

                    case QiniuAuthType.Upload:
                        ApplyUploadAuth(request);
                        break;

                    case QiniuAuthType.Download:
                        ApplyDownloadAuth(request);
                        break;

                    case QiniuAuthType.StreamManage:
                        await ApplyStreamManageAuthAsync(request).ConfigureAwait(false);
                        break;

                    default:
                        throw new NotSupportedException($"不支持的认证类型: {_authType}");
                }
            }
            catch (Exception ex) when (!(ex is ArgumentNullException || ex is NotSupportedException))
            {
                // 包装其他异常为InvalidOperationException，提供更明确的错误信息
                throw new InvalidOperationException($"应用{_authType}认证时发生错误: {ex.Message}", ex);
            }
        }

        #region 私有认证方法实现

        /// <summary>
        /// 异步应用传统管理API认证（QBox格式）
        /// 生成QBox格式的Authorization头，适用于传统的七牛云管理API
        /// </summary>
        /// <param name="request">HTTP请求对象</param>
        /// <remarks>
        /// QBox认证流程：
        /// 1. **URL提取**：从请求中提取完整的URL地址
        /// 2. **请求体读取**：异步读取请求体内容（如果存在）
        /// 3. **签名计算**：使用QBox签名算法生成签名
        /// 4. **头部设置**：设置Authorization头为"QBox AccessKey:签名"
        /// 
        /// 适用API：
        /// - 早期版本的存储桶管理API
        /// - 部分文件管理API
        /// - 统计查询API的旧版本
        /// 
        /// 异步处理优势：
        /// - 异步读取请求体内容，避免阻塞线程
        /// - 使用ConfigureAwait(false)避免上下文切换开销
        /// - 适合处理包含大型请求体的API调用
        /// </remarks>
        private async Task ApplyManageApiAuthAsync(HttpRequestMessage request)
        {
            // 获取完整的请求URL
            var url = request.RequestUri?.ToString() ?? "";

            // 异步获取请求体的字节数组（GET请求通常为null）
            var body = await GetRequestBodyBytesAsync(request).ConfigureAwait(false);

            // 使用QBox签名算法生成令牌
            var token = _signature.SignRequest(url, body);

            // 设置QBox格式的Authorization头
            request.Headers.Authorization = new AuthenticationHeaderValue("QBox", token);
        }

        /// <summary>
        /// 异步应用V2版本管理API认证（Qiniu格式）
        /// 生成Qiniu格式的Authorization头，这是推荐的认证方式
        /// </summary>
        /// <param name="request">HTTP请求对象</param>
        /// <remarks>
        /// Qiniu V2认证流程：
        /// 1. **请求信息提取**：提取HTTP方法、URL、头部信息
        /// 2. **请求体读取**：异步读取请求体内容
        /// 3. **头部转换**：将HTTP头部转换为字典格式
        /// 4. **签名计算**：使用QiniuV2签名算法生成签名
        /// 5. **头部设置**：设置Authorization头为"Qiniu AccessKey:签名"
        /// 
        /// 相比QBox格式的优势：
        /// - **安全性更高**：签名包含HTTP方法、Host等更多信息
        /// - **防篡改能力强**：包含请求头信息，防止请求被修改
        /// - **支持自定义头部**：可以验证X-Qiniu-*自定义头部
        /// - **标准化**：符合现代API安全标准和最佳实践
        /// 
        /// 适用API：
        /// - 新版存储桶管理API（推荐）
        /// - CDN管理API
        /// - 数据处理API
        /// - 大部分七牛云服务的最新版本API
        /// </remarks>
        private async Task ApplyManageApiV2AuthAsync(HttpRequestMessage request)
        {
            // 获取HTTP请求方法（GET、POST等）
            var method = request.Method.Method;

            // 获取完整的请求URL
            var url = request.RequestUri?.ToString() ?? "";

            // 转换HTTP头部为字典格式，供签名算法使用
            var headers = ConvertHeaders(request.Headers);

            // 异步获取请求体内容（字符串格式）
            var body = await GetRequestBodyAsync(request).ConfigureAwait(false);

            // 使用V2签名算法生成令牌
            var token = _signature.SignRequestV2(method, url, headers, body);

            // 设置Qiniu格式的Authorization头
            request.Headers.Authorization = new AuthenticationHeaderValue("Qiniu", token);
        }

        /// <summary>
        /// 应用上传认证
        /// 为文件上传请求添加上传凭证，通常以自定义头部形式提供
        /// </summary>
        /// <param name="request">HTTP请求对象</param>
        /// <exception cref="ArgumentNullException">当request为null时抛出</exception>
        /// <exception cref="InvalidOperationException">当上传策略为空时抛出</exception>
        /// <remarks>
        /// 上传认证流程：
        /// 1. **策略验证**：验证上传策略是否存在和有效
        /// 2. **凭证生成**：使用上传策略生成带数据的签名凭证
        /// 3. **头部添加**：将凭证添加为X-Qiniu-Upload-Token头部
        /// 
        /// 凭证格式：AccessKey:签名:Base64编码的上传策略
        /// 
        /// 注意事项：
        /// - 上传认证通常不使用标准的Authorization头
        /// - 实际的上传API可能需要将token作为表单字段提交
        /// - 不同的上传方式（直传、分片上传等）可能有不同的token传递方式
        /// - 这里添加为自定义头，实际使用时可能需要根据具体API调整
        /// 
        /// 同步方法说明：
        /// 此方法不涉及异步IO操作，仅进行纯计算和头部设置，因此保持同步实现
        /// </remarks>
        private void ApplyUploadAuth(HttpRequestMessage request)
        {
            ArgumentNullException.ThrowIfNull(request, nameof(request));

            if (string.IsNullOrEmpty(_uploadPolicy))
                throw new InvalidOperationException("上传策略不能为空");

            // 使用上传策略生成带数据的签名凭证
            var token = _signature.SignWithData(_uploadPolicy);

            // 上传通常使用表单字段而不是Authorization头
            // 这里添加为自定义头，实际使用时可能需要根据具体API调整
            request.Headers.Add("X-Qiniu-Upload-Token", token);
        }

        /// <summary>
        /// 应用下载认证
        /// 为私有文件下载请求生成带签名的URL，不使用Authorization头
        /// </summary>
        /// <param name="request">HTTP请求对象</param>
        /// <exception cref="ArgumentNullException">当request为null时抛出</exception>
        /// <exception cref="InvalidOperationException">当请求URI为null时抛出</exception>
        /// <remarks>
        /// 下载认证流程：
        /// 1. **URL提取**：获取原始下载URL
        /// 2. **过期时间计算**：计算链接过期的Unix时间戳
        /// 3. **URL修改**：添加过期时间参数（e=时间戳）
        /// 4. **签名生成**：对包含过期时间的URL进行签名
        /// 5. **最终URL**：将签名作为token参数添加到URL中
        /// 6. **请求更新**：更新请求的目标URL
        /// 
        /// URL格式变化：
        /// - 原始：https://domain.com/file.jpg
        /// - 添加过期：https://domain.com/file.jpg?e=1640995200
        /// - 最终：https://domain.com/file.jpg?e=1640995200&amp;token=AccessKey:签名
        /// 
        /// 适用场景：
        /// - 私有存储桶的文件访问
        /// - 需要时间限制的文件下载
        /// - 防止直链盗用的文件保护
        /// - 临时分享链接生成
        /// 
        /// 同步方法说明：
        /// 此方法不涉及异步IO操作，仅进行URL构建和签名计算，因此保持同步实现
        /// </remarks>
        private void ApplyDownloadAuth(HttpRequestMessage request)
        {
            ArgumentNullException.ThrowIfNull(request, nameof(request));

            if (request.RequestUri == null)
                throw new InvalidOperationException("下载认证需要有效的请求URI");

            // 获取原始下载URL
            var url = request.RequestUri.ToString();

            // 计算过期时间戳（Unix时间戳）
            var expiryTimestamp = DateTimeOffset.UtcNow.Add(_expiry ?? TimeSpan.FromHours(1)).ToUnixTimeSeconds();

            // 为URL添加过期时间参数
            var urlWithExpiry = url.Contains('?')
                ? $"{url}&e={expiryTimestamp}"  // URL已有参数，使用&连接
                : $"{url}?e={expiryTimestamp}"; // URL无参数，使用?开始

            // 对包含过期时间的URL进行签名
            var token = _signature.Sign(urlWithExpiry);

            // 生成最终的带签名URL
            var finalUrl = $"{urlWithExpiry}&token={token}";

            // 更新请求的目标URL
            request.RequestUri = new Uri(finalUrl);
        }

        /// <summary>
        /// 异步应用流管理认证
        /// 用于七牛云直播流管理API的认证，对请求体进行签名
        /// </summary>
        /// <param name="request">HTTP请求对象</param>
        /// <remarks>
        /// 流管理认证流程：
        /// 1. **请求体读取**：异步获取请求体内容
        /// 2. **带数据签名**：使用请求体生成带数据的签名
        /// 3. **头部设置**：设置Qiniu格式的Authorization头
        /// 
        /// 适用API：
        /// - 直播流的创建、删除、查询
        /// - 流状态管理和控制
        /// - 录制管理功能
        /// - 截图和水印功能
        /// - 流量统计和分析等直播相关功能
        /// 
        /// 特点：
        /// - 使用带数据签名，将请求体包含在签名计算中
        /// - 使用Qiniu格式的Authorization头
        /// - 主要用于POST请求场景
        /// - 适合流管理API通常包含较大请求体的特点
        /// 
        /// 异步处理：
        /// - 异步读取请求体内容，避免阻塞线程
        /// - 适合处理流管理API的复杂请求体
        /// </remarks>
        private async Task ApplyStreamManageAuthAsync(HttpRequestMessage request)
        {
            // 异步获取请求体内容用于签名
            var body = await GetRequestBodyAsync(request).ConfigureAwait(false);

            // 对请求体进行带数据签名
            var token = _signature.SignWithData(body);

            // 设置Qiniu格式的Authorization头
            request.Headers.Authorization = new AuthenticationHeaderValue("Qiniu", token);
        }

        #endregion

        #region 异步辅助方法

        /// <summary>
        /// 异步获取HTTP请求体的字节数组
        /// 用于需要对二进制请求体进行签名的场景
        /// </summary>
        /// <param name="request">HTTP请求对象</param>
        /// <returns>请求体的字节数组，如果没有请求体或读取失败则返回null</returns>
        /// <remarks>
        /// 异步实现优势：
        /// - **非阻塞处理**：避免阻塞调用线程，提高并发性能
        /// - **内存效率**：适合处理大型请求体，避免内存溢出
        /// - **上下文优化**：使用ConfigureAwait(false)避免不必要的上下文切换
        /// - **异常安全**：安全的异常处理，失败时返回null而不抛出异常
        /// 
        /// 适用场景：
        /// - QBox格式签名中需要包含请求体的场景
        /// - 需要对二进制内容进行签名验证的API
        /// - 文件上传等包含二进制数据的请求
        /// - 需要计算请求体哈希值的认证场景
        /// 
        /// 性能考虑：
        /// - 异步读取避免线程阻塞
        /// - 内存使用优化，适合大文件处理
        /// - 错误恢复机制，提高系统稳定性
        /// </remarks>
        private static async Task<byte[]?> GetRequestBodyBytesAsync(HttpRequestMessage request)
        {
            if (request.Content == null)
                return null;

            try
            {
                // 异步读取请求体字节数组，避免上下文切换
                return await request.Content.ReadAsByteArrayAsync().ConfigureAwait(false);
            }
            catch (Exception)
            {
                // 读取失败时返回null，由调用方决定如何处理
                // 可以在这里添加日志记录
                return null;
            }
        }

        /// <summary>
        /// 异步获取HTTP请求体的字符串内容
        /// 用于需要对文本请求体进行签名的场景
        /// </summary>
        /// <param name="request">HTTP请求对象</param>
        /// <returns>请求体的字符串内容，如果没有请求体或读取失败则返回空字符串</returns>
        /// <remarks>
        /// 异步实现优势：
        /// - **大文件友好**：异步处理避免阻塞，特别适合处理大型JSON或XML请求体
        /// - **性能优化**：使用ConfigureAwait(false)减少上下文切换开销
        /// - **稳定性保证**：安全的异常处理，确保方法始终返回有效值
        /// - **编码处理**：自动处理字符编码转换，支持各种文本格式
        /// 
        /// 适用场景：
        /// - Qiniu V2格式签名中需要包含请求体的场景
        /// - JSON、XML、表单等文本格式的请求体处理
        /// - 流管理API等需要对请求体内容进行签名的场景
        /// - 需要验证请求体完整性的认证场景
        /// 
        /// 字符编码：
        /// - 默认使用UTF-8编码读取内容
        /// - 适合大部分现代Web API的文本内容格式
        /// - 自动处理BOM和编码检测
        /// </remarks>
        private static async Task<string> GetRequestBodyAsync(HttpRequestMessage request)
        {
            if (request.Content == null)
                return "";

            try
            {
                // 异步读取请求体字符串内容，避免上下文切换
                return await request.Content.ReadAsStringAsync().ConfigureAwait(false);
            }
            catch (Exception)
            {
                // 读取失败时返回空字符串，确保签名算法能正常工作
                // 可以在这里添加日志记录
                return "";
            }
        }

        #endregion

        #region 同步辅助方法

        /// <summary>
        /// 将HttpRequestHeaders转换为字典格式
        /// 用于签名算法中需要处理HTTP头部信息的场景
        /// </summary>
        /// <param name="headers">HTTP请求头集合</param>
        /// <returns>头部信息的字典，键为头部名称，值为头部值（多个值用逗号分隔）</returns>
        /// <remarks>
        /// 转换规则：
        /// - **名称保持**：头部名称保持原始大小写，不做转换
        /// - **值合并**：多个相同名称的头部值用", "分隔（符合HTTP标准）
        /// - **用途专一**：专门用于QiniuV2签名算法中的头部处理
        /// - **性能优化**：使用字典提供快速的头部信息查找
        /// 
        /// HTTP头部处理标准：
        /// - 遵循RFC 7230关于HTTP头部的规范
        /// - 多值头部使用逗号+空格分隔
        /// - 保持头部名称的原始大小写
        /// - 支持自定义头部（如X-Qiniu-*）
        /// 
        /// 示例转换：
        /// ```
        /// Accept: application/json, text/plain
        /// Content-Type: application/json
        /// X-Qiniu-Date: 20240315T120000Z
        /// ```
        /// 
        /// 性能考虑：
        /// - 此方法为纯内存操作，不涉及IO，因此保持同步实现
        /// - 转换过程快速，不会影响整体异步性能
        /// - 结果字典供签名算法使用，便于头部信息的查找和处理
        /// - 内存使用合理，适合大部分HTTP请求的头部数量
        /// </remarks>
        private static Dictionary<string, string> ConvertHeaders(HttpRequestHeaders headers)
        {
            var result = new Dictionary<string, string>();
            foreach (var header in headers)
            {
                // 将头部的多个值用逗号空格连接，符合HTTP标准
                result[header.Key] = string.Join(", ", header.Value);
            }
            return result;
        }

        #endregion
    }
}
